﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using Fluid.Controls;
using TouchRC.BarManagers;
using TouchRC.Classes;
using TouchRC.Custom_Controls;
using System.Drawing;
using TouchRC.Logic;
using System.Threading;
using Microsoft.Drawing;
using TouchRC.Themes;
using TouchRC.MetadataCaching;
using System.IO;
using TouchRC.Logging;

namespace TouchRC
{
    public class NowPlayingPanel : FluidPanelBase
    {
        #region Private Members

        private MediaBase m_MediaItem = null;
        private string m_DisplayedTitle = string.Empty;
        private TimeSpan m_DisplayedTotalTime = TimeSpan.Zero;
        private bool m_WorkerThreadDone = false;
        //private Thread m_MyWorkerThread;

        private FluidLabel m_MediaTitle;
        private NowPlayingButtonPanel m_ButtonPanel;
        private ProgressBar m_ProgressBar;
        private FluidLabel m_CurrentTime;
        private FluidLabel m_TotalTime;
        private TouchButton m_Image;
        private IMediaSummary m_MediaSummary;

        private bool m_IsAlreadyVisible = false;
        //private static NowPlayingPanel m_Instance = null;

        #endregion

        public void ShowNowPlaying()
        {
            if (!m_IsAlreadyVisible)
            {
                m_IsAlreadyVisible = true;
                StartAsyncListening();
                Show(ShowTransition.FromRight);
            }
        }

        public void HideNowPlaying()
        {
            if (m_IsAlreadyVisible)
            {
                m_IsAlreadyVisible = false;
                StopAsyncListening();
                Close(ShowTransition.FromLeft);
            }
        }

        //public static NowPlayingPanel Instance
        //{
        //    get
        //    {
        //        if (m_Instance == null)
        //        {
        //            m_Instance = new NowPlayingPanel();
        //        }
        //        return m_Instance;
        //    }
        //}

        #region FluidPanelBase Abstract Methods

        public override void SetControlPositions(ScreenOrientation screenOrientation)
        {
            int screenHeight = AppSettings.ScreenResolution.Height;
            int screenWidth = AppSettings.ScreenResolution.Width;
            int baseControlHeight = AppSettings.BaseControlHeight;
            int margin = 10;
            int imageHeight = 100;
            int imageWidth = 100;
            int width = screenWidth - (2 * margin);
            int progressX = margin;
            int progressHeight = baseControlHeight;
            int progressWidth = width;
            int buttonsX = margin;
            int buttonsWidth = width;
            int timesHeight = 20;
            int timesMargin = 5;
            int indButtonHeight = 40;

            int imageX;
            int imageY;

            int titleX;
            int titleY;
            int titleWidth;
            int titleHeight;

            int progressY;

            int buttonsY;
            int buttonsHeight;

            if (screenOrientation == ScreenOrientation.Landscape)
            {
                imageX = 2*margin;
                imageY = 2*margin;

                titleX = imageX + margin + imageWidth;
                titleY = baseControlHeight + margin;
                titleWidth = screenWidth - margin - titleX;
                titleHeight = margin + imageHeight - titleY;

                buttonsHeight = indButtonHeight;
                buttonsY = screenHeight - (buttonsHeight + margin);

                progressY = screenHeight - (2 * margin) - buttonsHeight - progressHeight;

                m_MediaTitle.Alignment = StringAlignment.Near;
                m_MediaTitle.LineAlignment = StringAlignment.Near;
            }
            else
            {
                imageWidth = width;
                imageX = (screenWidth - imageWidth) / 2;
                imageY = baseControlHeight + margin;

                titleX = margin;
                titleY = margin + imageY + imageHeight;
                titleWidth = width;

                buttonsHeight = (2 * indButtonHeight) + margin;
                buttonsY = screenHeight - (margin + buttonsHeight);

                progressY = buttonsY - (margin + progressHeight);

                titleHeight = screenHeight - (progressY - (timesHeight + timesMargin)) - margin;

                m_MediaTitle.Alignment = StringAlignment.Center;
                //m_MediaTitle.LineAlignment = StringAlignment.Center;
            }

            int timesWidth = progressWidth / 2;
            int timesY = progressY - (timesHeight + timesMargin);

            int currentTimeX = margin;

            int totalTimeX = margin + timesWidth;

            m_ProgressBar.Bounds = new Rectangle(m_ProgressBar.ScaleX(progressX), m_ProgressBar.ScaleY(progressY), 
                m_ProgressBar.ScaleX(progressWidth), m_ProgressBar.ScaleY(progressHeight));

            m_ButtonPanel.SetNewBounds = new Rectangle(m_ButtonPanel.ScaleX(buttonsX), m_ButtonPanel.ScaleY(buttonsY), 
                m_ButtonPanel.ScaleX(buttonsWidth), m_ButtonPanel.ScaleY(buttonsHeight));

            m_MediaTitle.Bounds = new Rectangle(m_MediaTitle.ScaleX(titleX), m_MediaTitle.ScaleY(titleY), 
                m_MediaTitle.ScaleX(titleWidth), m_MediaTitle.ScaleY(titleHeight));

            m_CurrentTime.Bounds = new Rectangle(m_CurrentTime.ScaleX(currentTimeX), m_CurrentTime.ScaleY(timesY), 
                m_CurrentTime.ScaleX(timesWidth), m_CurrentTime.ScaleY(timesHeight));

            m_TotalTime.Bounds = new Rectangle(m_TotalTime.ScaleX(totalTimeX), m_TotalTime.ScaleY(timesY), 
                m_TotalTime.ScaleX(timesWidth), m_TotalTime.ScaleY(timesHeight));

            m_Image.Bounds = new Rectangle(m_Image.ScaleX(imageX), m_Image.ScaleY(imageY), 
                m_Image.ScaleX(imageWidth), m_Image.ScaleY(imageHeight));

            AdjustTextAndImagePositions();
        }

        public override void RefreshValues()
        {
            m_ProgressBar.SetNewValues(m_MediaItem.CurrentTrackTime, m_DisplayedTotalTime);  //.MediaItem = m_MediaItem;
            if (m_MediaItem != null)
            {
                if (m_CurrentTime.Text != m_MediaItem.CurrentTrackTime.ToString())
                    m_CurrentTime.Text = m_MediaItem.CurrentTrackTime.ToString();
                
            }

            if (m_TotalTime.Text != m_DisplayedTotalTime.ToString())
                m_TotalTime.Text = m_DisplayedTotalTime.ToString();

            if (m_MediaTitle.Text != m_DisplayedTitle)
            {
                m_MediaTitle.Text = m_DisplayedTitle;
                AdjustTextAndImagePositions();
            }   
            // Invalidate();
        }

        public override void AddControls()
        {
            Controls.Add(m_CurrentTime);
            Controls.Add(m_MediaTitle);
            Controls.Add(m_ButtonPanel);
            Controls.Add(m_ProgressBar);
            Controls.Add(m_TotalTime);
            Controls.Add(m_Image);
        }

        public override void InitPanelControls()
        {
            m_TotalTime = new FluidLabel();
            m_ProgressBar = new ProgressBar();
            m_ButtonPanel = new NowPlayingButtonPanel();
            m_MediaTitle = new FluidLabel();
            m_CurrentTime = new FluidLabel();
            m_Image = new TouchButton();
        }

        public override List<BarOption> GetBarOptions()
        {
            //BarOption home = new BarOption();
            //home.Image = ImageFactory.GetBitmap(ImageTypes.Cross);
            //home.Click += new EventHandler<EventArgs>(home_Click);
            return new List<BarOption>();
        }

        public override void Back()
        {
        }

        void home_Click(object sender, EventArgs e)
        {
            HideOptionsBar();
            MainMenuPanel.Instance.ShowAndSelectSelectedItem();
        }

        #endregion

        protected override void InitControl()
        {
            base.InitControl();

            EnableNowPlayingGesture = false;

            HeaderText = "Now Playing";

            m_TotalTime.Alignment = StringAlignment.Far;

            m_CurrentTime.ForeColor = Theme.CurrentTheme.HeaderColor;
            m_TotalTime.ForeColor = Theme.CurrentTheme.HeaderColor;

            m_MediaTitle.ForeColor = Theme.CurrentTheme.HeaderColor;

            m_Image.Click += new EventHandler(m_Image_Click);
        }

        void m_Image_Click(object sender, EventArgs e)
        {
            if (m_MediaSummary != null)
            {
                MetadataPanel.ShowMetadataPanel(m_MediaSummary, false);
            }
        }

        public override void OnGesture(GestureEventArgs e)
        {
            if (e.Gesture == Gesture.Left)
            {
                e.Handled = true;
                HideNowPlaying();
            }
            else
            {
                base.OnGesture(e);
            }
        }

        private void AdjustTextAndImagePositions()
        {
            if (AppSettings.CurrentOrientation == ScreenOrientation.Portrait)
            {
                Size bob;
                using (Graphics graphics = CreateGraphics())
                {
                    bob = graphics.MeasureStringEx(m_DisplayedTitle, Theme.CurrentTheme.StandardFont, 
                        m_MediaTitle.ClientRectangle.Width);
                }

                int margin = 10;

                int titleX = m_CurrentTime.UnscaleY(m_CurrentTime.Top) - (margin + m_CurrentTime.UnscaleY(bob.Height));
                int imageHeight = titleX - margin - m_Image.UnscaleY(m_Image.Top);

                titleX = m_MediaTitle.ScaleY(titleX);
                imageHeight = m_Image.ScaleY(imageHeight);

                m_MediaTitle.Top = titleX;
                m_Image.Height = imageHeight;

                int h = bob.Width;
            }
        }

        private void StartAsyncListening()
        {
            SetDefaultValues();

            ThreadPool.QueueUserWorkItem(MyMedia);

            m_WorkerThreadDone = false;
        }

        private void StopAsyncListening()
        {
            m_WorkerThreadDone = true;
        }

        #region Threading/Asynchronous shite

        private delegate void UpdateMedia(MediaBase media);
        private void UpdateMediaMethod(MediaBase media)
        {
            MediaItem = media;
        }

        private void MyMedia(Object stateInfo)
        {
            UpdateMedia mediaUpdate = UpdateMediaMethod;

            AsynchronousClient.Init(MainMenuPanel.CurrentComputer);
            MediaBase media;

            while (!m_WorkerThreadDone)
            {
                try
                {
                    string response = AsynchronousClient.OpenAndReceive();
                    if (response.StartsWith("ERROR"))
                    {
                        m_WorkerThreadDone = true;
                        TouchRC.PasswordForm.DisplayError error = TouchRC.PasswordForm.Instance.DisplayErrorMethod;
                        PasswordForm.Instance.Invoke(error, new object[] { response });
                    }
                    else
                    {
                        media = ListenerLogic.ParseReturnValue(response);
                        PasswordForm.Instance.Invoke(mediaUpdate, new object[] { media });
                    }
                }
                catch (Exception e)
                {
                    Logger.LogMessage("Error retrieving currently playing media: {0}", e.Message);
                }
                Thread.Sleep(0);
            }
        }

        private delegate void UpdateMovieSummary(IMediaSummary summary);
        private void UpdateMovieMethod(IMediaSummary summary)
        {
            if (summary != null)
            {
                if (!string.IsNullOrEmpty(summary.Name))
                {
                    m_DisplayedTitle = summary.Name;
                }
                if (summary.Poster != null && File.Exists(summary.Poster.FullName))
                {
                    IImagingFactory factory = ImagingFactory.GetImaging();
                    IImage image;
                    factory.CreateImageFromFile(summary.Poster.FullName, out image);
                    m_Image.Image = image;
                }
                // RefreshValues();
                if (m_DisplayedTotalTime == TimeSpan.Zero)
                {
                    ThreadPool.QueueUserWorkItem(TotalTime);
                }
            }
        }

        private void MyMovie(Object stateInfo)
        {
            UpdateMovieSummary movieSummaryDelegate = UpdateMovieMethod;

            m_MediaSummary = MainMenuPanel.CurrentComputer.MetadataCollection.QueryFileName(m_DisplayedTitle);

            if (m_MediaSummary != null)
            {
                PasswordForm.Instance.Invoke(movieSummaryDelegate, new object[] { m_MediaSummary });
            }
        }

        private delegate void UpdateTotalPlayingTime(VmcCMetaData metadata);
        private void UpdateTotalTimeMethod(VmcCMetaData metadata)
        {
            m_DisplayedTotalTime = metadata.Duration;
            if (m_MediaItem.Title != metadata.Title
                && metadata.Title != null)
                m_DisplayedTitle = metadata.Title;
        }

        private void TotalTime(Object stateInfo)
        {
            UpdateTotalPlayingTime totalTimeDelegate = UpdateTotalTimeMethod;

            VmcControllerRemote remote = new VmcControllerRemote(MainMenuPanel.CurrentComputer);
            VmcCMetaData data = remote.GetCurrentlyPlayingMetaData();

            if (data != null)
            {
                PasswordForm.Instance.Invoke(totalTimeDelegate, new object[] { data });
            }
        }

        #endregion

        private void SetDefaultValues()
        {
            MediaBase defaultBase = new MediaBase();
            defaultBase.CurrentTrackTime = TimeSpan.Zero;
            defaultBase.Image = ImageFactory.GetMenuOptionImage(MenuItemOption.MusicQueue);
            defaultBase.PlayState = false;
            defaultBase.Title = "No Selected Title";
            defaultBase.TotalTrackTime = TimeSpan.Zero;

            m_MediaItem = defaultBase;

            m_DisplayedTitle = defaultBase.Title;
            m_Image.Image = defaultBase.Image;

            m_MediaSummary = null;

            RefreshValues();
        }

        public MediaBase MediaItem
        {
            get { return m_MediaItem; }
            set
            {
                if (m_MediaItem != value)
                {
                    if (value == null)
                    {
                        SetDefaultValues();
                    }
                    else
                    {
                        if (m_MediaItem.ToString() != value.ToString() ||
                            m_MediaItem.GetType() != value.GetType())
                        {
                            m_MediaSummary = null;
                            m_Image.Image = value.Image;
                            m_DisplayedTitle = value.ToString();

                            if (value.TotalTrackTime.TotalSeconds == 0)
                            {
                                ThreadPool.QueueUserWorkItem(TotalTime);
                            }
                            else
                            {
                                m_DisplayedTotalTime = value.TotalTrackTime;
                            }

                            if (value is MediaVideo)
                            {
                                if (MainMenuPanel.CurrentComputer.MetadataCacheDir != null &&
                                    Directory.Exists(MainMenuPanel.CurrentComputer.MetadataCacheDir.FullName))
                                    ThreadPool.QueueUserWorkItem(MyMovie);
                            }
                        }
                        
                        m_MediaItem = value;
                        RefreshValues();
                    }
                }
            }
        }
    }
}
